import JDBCBean.Customers;
import JDBCBean.Order;
import org.junit.Test;
import java.lang.reflect.Field;
import java.sql.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import JDBCUtiles.Utils;

/**
 * @Author 不知名网友鑫
 * @Date 2022/6/25
 * 使用PrepareStatement实现通用的CRUD操作。
 **/
public class prepareStatementTest {

    @Test
    public void test(){
        //测试通用的增删改操作。
        String sql1 = "delete from customers where id = ?";
        update(sql1,3);

        //测试通用的查询操作。
        //如果列名与属性名不同，必须声明sql为列的别名，别名应与属性名相同。
        String sql = "select id,name,email,birth from customers where id < ?";
        List<Customers> customersList = selectAll(Customers.class, sql, 12);
        customersList.forEach(System.out::println);

    }
    //通用的增删改操作,sql中占位符的个数与可变形参长度相同
    public static void update(String sql,Object ...obj ){
        PreparedStatement ps = null;
        Connection connection = null;
        try {
            //1. 获取数据库连接
            connection =Utils.getConnection();
            //2. 预编译sql语句，返回PreparedStatement
            ps = connection.prepareStatement(sql);
            //3. 填充占位符
            for(int i=0;i<obj.length;i++){
                ps.setObject(i+1,obj[i]);
            }
            //4. 执行操作
            ps.execute();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //5. 关闭资源
            Utils.closeResource(connection,ps);
        }
    }
    //针对所有表的通用的查找操作。
    public <T> List<T> selectAll(Class<T> clazz, String sql, Object ...obj){
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            //1. 获取数据库连接
            conn = Utils.getConnection();
            //2. 预编译sql语句
            ps = conn.prepareStatement(sql);
            //3. 填充占位符
            for(int i=0;i<obj.length;i++) {
                ps.setObject(i+1,obj[i]);
            }
            //4. 调用executeQuery()方法执行操作，并返回结果集。
            rs = ps.executeQuery();
            //5. 返回结果集的元数据，以便获取列数、列名。
            ResultSetMetaData metaData = rs.getMetaData();
            int columnCount = metaData.getColumnCount();
            List<T> list = new ArrayList<>();
            while(rs.next()){
                T t = clazz.newInstance();
                for(int i=0;i<columnCount;i++){
                    //使用结果集获取columnValue。
                    Object columnValue = rs.getObject(i + 1);
                    //使用元数据获取列名/列的别名。
                    String columnName = metaData.getColumnLabel(i + 1);
                    //使用反射，给动态对象的columnName属性，赋值为columnValue。
                    Field field = clazz.getDeclaredField(columnName);
                    field.setAccessible(true);
                    field.set(t,columnValue);
                }
                list.add(t);
            }
            return list;
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            Utils.closeResource(conn,ps,rs);
        }
    }

    //针对所有表，查询一个结果的通用操作。
    public <T> T select(Class<T> clazz,String sql,Object ...obj){
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            conn = Utils.getConnection();
            ps = conn.prepareStatement(sql);
            for(int i=0;i<obj.length;i++) {
                ps.setObject(i+1,obj[i]);
            }
            rs = ps.executeQuery();
            ResultSetMetaData metaData = rs.getMetaData();
            int columnCount = metaData.getColumnCount();
            if(rs.next()){
                T t = clazz.newInstance();
                for(int i=0;i<columnCount;i++){
                    Object columnValue = rs.getObject(i + 1);
                    String columnName = metaData.getColumnLabel(i + 1);
                    Field field = clazz.getDeclaredField(columnName);
                    field.setAccessible(true);
                    field.set(t,columnValue);
                }
                return t;

            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            Utils.closeResource(conn,ps,rs);
        }
        return null;
    }


    //针对Order表的通用查询操作
    public static Order selectOrder(String sql,Object ...obj){
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
             conn = Utils.getConnection();
             ps = conn.prepareStatement(sql);
            for(int i=0;i<obj.length;i++) {
                ps.setObject(i+1,obj[i]);
            }
             rs = ps.executeQuery();
            ResultSetMetaData metaData = rs.getMetaData();
            int columnCount = metaData.getColumnCount();
            if(rs.next()){
                Order order = new Order();
                for(int i=0;i<columnCount;i++){
                    Object columnValue = rs.getObject(i + 1);
                    String columnName = metaData.getColumnLabel(i + 1);
                    Field field = Order.class.getDeclaredField(columnName);
                    field.setAccessible(true);
                    field.set(order,columnValue);
                }
                return order;

            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            Utils.closeResource(conn,ps,rs);
        }
        return null;

    }

    //针对customer表的通用查询操作。
    public static Customers selectCustomers(String sql,Object ...obj){
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet resultSet = null;
        try {
            //1. 获取数据库连接
            conn = Utils.getConnection();
            //2. 预编译sql
            ps = conn.prepareStatement(sql);
            //3. 填充占位符
            for(int i=0;i< obj.length;i++) {
                ps.setObject(i+1, obj[i]);
            }
            //4. 获取结果集
            resultSet = ps.executeQuery();

            //5.1 获取结果集的元数据——获取结果集中列的个数。
            ResultSetMetaData metaData = resultSet.getMetaData();
            int columnCount = metaData.getColumnCount();
            if(resultSet.next()){
                Customers customers = new Customers();
                for(int i=0;i<columnCount;i++){
                    //获取属性的值。
                    Object columValue = resultSet.getObject(i+1);
                    // 获取当前列名，为反射准备。
                    //获取当前列名：getColumnName()——不推荐
                    //获取当前列的别名：getColumnLabel——推荐
                    String columnName = metaData.getColumnLabel(i + 1);
                    //使用反射，给customers对象指定的columnName属性，赋值。
                    Field field = Customers.class.getDeclaredField(columnName);
                    field.setAccessible(true);
                    field.set(customers,columValue);
                }
                return customers;
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            Utils.closeResource(conn,ps,resultSet);
        }
        return  null;
    }


    //使用PrepareStatement往数据库中【添加】数据。
    @Test
    public void testadd() {
        Connection connection = null;
        PreparedStatement ps = null;
        try {
            //1. 建立数据库连接：
            Utils.getConnection();
            //2. 预编译sql语句，返回PrepareStatement的实例
            String sql  = "insert into customers(name,email,birth)values(?,?,?)";
            ps = connection.prepareStatement(sql);
            //3. 填充占位符-?
            ps.setString(1,"111");
            ps.setString(2,"111@qq.com");
            //关于日期的写法
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            java.util.Date parse = simpleDateFormat.parse("1000-01-01");

            ps.setDate(3,  new Date(parse.getTime()));

            //4. 执行操作
            ps.execute();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }  finally {
            Utils.closeResource(connection,ps);
        }
    }
    //【修改】数据customers库表中的记录
    @Test
    public void testUpdate(){
        PreparedStatement ps = null;
        Connection connection = null;
        //1. 获取数据库连接
        try {
             connection =Utils.getConnection();
            //2. 预编译sql语句，返回PreparedStatement
            String sql = "update customers set name = ? where id = ?";
            ps = connection.prepareStatement(sql);
            //3. 填充占位符
            ps.setObject(1,"UPDATE");
            ps.setObject(2,18);
            //4. 执行操作
            ps.execute();
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            //5. 关闭资源
            Utils.closeResource(connection,ps);
        }

    }
    //查询操作。
    @Test
    public void selectTest(){
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet resultSet = null;
        try {
            //1. 连接数据库
            conn = Utils.getConnection();
            //2. 预编译sql语句
            String sql = "select id,name,email,birth from customers where id = ?";
            ps = conn.prepareStatement(sql);
            //3. 填充占位符
            ps.setObject(1,1);
            //4. 执行，并返回结果集。
            resultSet = ps.executeQuery();
            if(resultSet.next()){//next():1. 查询表中下一条是否存在记录；2. 指针下移。
                int id = resultSet.getInt(1);
                String name = resultSet.getString(2);
                String email = resultSet.getString(3);
                Date birth = resultSet.getDate(4);
                Customers customers = new Customers(id, name, email, birth);
                System.out.println(customers);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            //5. 关闭资源
            Utils.closeResource(conn,ps,resultSet);
        }
    }
}
